﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Chapter21.Models.BarrierSample
{
    using System.Threading;

    public static class Demo
    {
        public static void InvokeAll()
        {
            Action line = () =>
            {
                Console.ReadLine();
            };
            Invoke(BarrierClass, line);
        }
        public static void Invoke(params Action[] actions)
        {
            foreach (var action in actions)
            {
                action();
            }
        }
        public static void BarrierClass()
        {
            const int numberTasks = 2;
            const int partitionSize = 1000000;
            var data = new List<string>(FillData(partitionSize * numberTasks));
            var barrier = new Barrier(numberTasks + 1);
            var tasks = new Task<int[]>[numberTasks];
            for (int i = 0; i < numberTasks; i++)
            {
                int jobNumber = i;
                tasks[i] = Task.Run(() => CalculationInTask(jobNumber, partitionSize, barrier, data));
            }
            barrier.SignalAndWait();
            var resultCollection = tasks[0].Result.Zip(tasks[1].Result, (c1, c2) =>
                {
                    return c1 + c2;
                });
            var ch = 'a';
            int sum = 0;
            foreach (var x in resultCollection)
            {
                Console.WriteLine("{0}, 计数: {1}", ch++, x);
                sum += x;
            }
            Console.WriteLine("主线程完成 {0}", sum);
            Console.WriteLine("剩下 {0}", barrier.ParticipantsRemaining);
        }

        private static IEnumerable<string> FillData(int size)
        {
            var data = new List<string>(size);
            var r = new Random();
            for (int i = 0; i < size; i++)
            {
                data.Add(GetString(r));
            }
            return data;
        }
        private static string GetString(Random r)
        {
            var sb = new StringBuilder(6);
            for (int i = 0; i < 6; i++)
            {
                sb.Append((char)(r.Next(26) + 97));
            }
            return sb.ToString();
        }
        private static int[] CalculationInTask(int jobNumber, int partitionSize, Barrier barrier, IList<string> coll)
        {
            var data = new List<string>(coll);
            var start = jobNumber * partitionSize;
            var end = start + partitionSize;
            Console.WriteLine("任务 {0}: 分割从 {1} 到 {2}", Task.CurrentId, start, end);
            int[] charCount = new int[26];
            for (int i = start; i < end; i++)
            {
                char c = data[i][0];
                charCount[c - 97]++;
            }
            Console.WriteLine("从任务 {0} 中计算完成. {1} 乘于 a, {2} 乘于 z", Task.CurrentId, charCount[0], charCount[25]);
            barrier.RemoveParticipant();
            Console.WriteLine("从参与者中移除任务 {0}, 剩下的参与者 {1}", Task.CurrentId, barrier.ParticipantsRemaining);
            return charCount;
        }
    }
}
